package com.mallcai.bigdata.ladon.service.report.impl;

import com.cake.bigdata.starter.exception.category.BusinessException;
import com.mallcai.bigdata.ladon.client.vo.ReportDataVO;
import com.mallcai.bigdata.ladon.client.param.ReportQueryParam;
import com.mallcai.bigdata.ladon.datasource.RunInfoResult;
import com.mallcai.bigdata.ladon.dpl.entity.common.Datasource;
import com.mallcai.bigdata.ladon.dpl.entity.report.Report;
import com.mallcai.bigdata.ladon.dpl.entity.report.ReportSql;
import com.mallcai.bigdata.ladon.service.report.impl.handler.IReportQueryHandler;
import com.mallcai.bigdata.ladon.service.report.impl.handler.IReportQueryPostHandler;
import com.mallcai.bigdata.ladon.service.report.impl.handler.IReportQueryPreHandler;
import com.mallcai.bigdata.ladon.vo.Pair;
import lombok.Getter;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author feixy
 * @version 1.0
 * @date 2019-07-19 20:30
 */
public class ReportQueryContext {

    private final ReportQueryPipeline pipeline;

    @Getter
    private final ReportQueryParam reportQueryParam;

    @Getter
    private final  Map<String,Object> originalParams;

    @Getter
    private final Long userId;

    private int currentIndex = 0;

    private boolean isCompleted = false; // 是否完成查询,如果已经完成,则后面所有的handler都不会继续处理

    private long                                totalCount;//分页查询时对应的总条数
    /**
     * 报表查询过程中的所有可用参数
     */
    private Map<String, ReportQueryParamHolder> queryParams = new HashMap<>();

    /**
     * sql语句最终使用的sql
     */
    private LinkedHashMap<Integer, Pair<ReportQueryParamHolder,Object>> sqlParams;

    /**
     * 内部参数
     */
    private Map<String, Object> innerParams = new HashMap<>();

    private RunInfoResult<ReportDataVO> result;

    public ReportQueryContext(ReportQueryPipeline pipeline, ReportQueryParam reportQueryParam, Map<String,Object> originalParams) {
        this.pipeline = pipeline;
        this.reportQueryParam = reportQueryParam;
        if(originalParams == null){
            this.originalParams = new HashMap<>();
        } else {
            this.originalParams = originalParams;
        }
        this.userId = reportQueryParam.getUserId() == null ? -1 : reportQueryParam.getUserId();
    }


    public RunInfoResult<ReportDataVO> getResult() {
        return result;
    }

    public void setResult(RunInfoResult<ReportDataVO> result) {
        if (result == null){
            throw new BusinessException("结果为空,非法的结果");
        }
        this.isCompleted = true;
        this.result = result;
    }


    public String getReportCode() {
        return reportQueryParam.getReportCode();
    }

    public Map<String, ReportQueryParamHolder> getQueryParams() {
        return this.queryParams;
    }

    public void putQueryParam(String key, ReportQueryParamHolder value){
        this.queryParams.put(key, value);
    }


    public void putInnerParam(String key, Object value){
        this.innerParams.put(key, value);
    }

    public <T> T getInnerParam(String key){
        return (T)this.innerParams.get(key);
    }

    public LinkedHashMap<Integer, Pair<ReportQueryParamHolder,Object>> getSqlParams() {
        return sqlParams;
    }

    public void setSqlParams(LinkedHashMap<Integer, Pair<ReportQueryParamHolder,Object>> sqlParams) {
        this.sqlParams = sqlParams;
    }

    public void next(){
        int size = this.pipeline.getReportQueryHandlerList().size();
        while (currentIndex < size && !isCompleted){
            IReportQueryHandler iReportQueryHandler = this.pipeline.getReportQueryHandlerList().get(currentIndex++);
            if (iReportQueryHandler instanceof IReportQueryPreHandler){
                ((IReportQueryPreHandler) iReportQueryHandler).preHandle(this);
                break;
            }
        }
        while(currentIndex > 0 && isCompleted){
            if (currentIndex == size){
                currentIndex--;
            }
            IReportQueryHandler iReportQueryHandler = this.pipeline.getReportQueryHandlerList().get(currentIndex--);
            if (iReportQueryHandler instanceof IReportQueryPostHandler){
                ((IReportQueryPostHandler) iReportQueryHandler).postHandle(this);
                break;
            }
        }

    }


    public Report getReport(){
        return getInnerParam(ReportQueryConstants.KEY_REPORT);
    }

    public void setReport( Report report){
        putInnerParam(ReportQueryConstants.KEY_REPORT, report);
    }

    public void setReportSql(ReportSql reportSql){
        putInnerParam(ReportQueryConstants.KEY_REPORT_SQL, reportSql);
    }

    public ReportSql getReportSql(){
        return getInnerParam(ReportQueryConstants.KEY_REPORT_SQL);
    }

    public Datasource getDatasource(){
        return getInnerParam(ReportQueryConstants.KEY_DATA_SOURCE);
    }

    public void setDatasource(Datasource datasource){
        putInnerParam(ReportQueryConstants.KEY_DATA_SOURCE, datasource);
    }

    public String getSql(){
        return getInnerParam(ReportQueryConstants.KEY_SQL);
    }

    public void setSql( String sql){
        putInnerParam(ReportQueryConstants.KEY_SQL, sql);
    }

    public long getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(long totalCount) {
        this.totalCount = totalCount;
    }
}
